#include "databasediff.h"
#include <QSqlDatabase>
#include <QSqlRecord>
#include <QSqlField>
#include <QSqlQuery>
#include <QSqlError>
#include <QMap>
#include <QList>
#include <QStringList>
#include <QVariant>

DatabaseDiff::DatabaseDiff(QObject *parent)
    : QObject(parent)
{
}

DatabaseInfo DatabaseDiff::extractDatabaseInfo(const QSqlDatabase &db)
{
    DatabaseInfo dbInfo(db.databaseName());
    
    if (!db.isOpen()) {
        emit comparisonError(tr("Database is not open"));
        return dbInfo;
    }
    
    // 获取所有表
    QStringList tables = db.tables();
    
    // 提取每个表的信息
    for (const QString &tableName : tables) {
        TableInfo tableInfo = extractTableInfo(db, tableName);
        dbInfo.tables.append(tableInfo);
    }
    
    return dbInfo;
}

TableInfo DatabaseDiff::extractTableInfo(const QSqlDatabase &db, const QString &tableName)
{
    TableInfo tableInfo(tableName);
    
    // 获取表的列信息
    QSqlRecord record = db.record(tableName);
    for (int i = 0; i < record.count(); ++i) {
        QSqlField field = record.field(i);
        tableInfo.columns[field.name()] = QVariant::typeToName(field.type());
    }
    
    // 获取主键信息（简化实现，仅适用于SQLite）
    if (db.driverName() == "QSQLITE") {
        QSqlQuery query(db);
        query.prepare("PRAGMA table_info(" + tableName + ")");
        if (query.exec()) {
            while (query.next()) {
                QString columnName = query.value("name").toString();
                int isPrimaryKey = query.value("pk").toInt();
                if (isPrimaryKey > 0) {
                    tableInfo.primaryKey.append(columnName);
                }
            }
        }
    }
    
    // 获取外键信息（简化实现，仅适用于SQLite）
    if (db.driverName() == "QSQLITE") {
        QSqlQuery query(db);
        query.prepare("PRAGMA foreign_key_list(" + tableName + ")");
        if (query.exec()) {
            while (query.next()) {
                QString columnName = query.value("from").toString();
                QString refTable = query.value("table").toString();
                QString refColumn = query.value("to").toString();
                tableInfo.foreignKeys[columnName] = refTable + "(" + refColumn + ")";
            }
        }
    }
    
    return tableInfo;
}

DatabaseDifference DatabaseDiff::compareDatabases(const QSqlDatabase &db1, const QSqlDatabase &db2)
{
    DatabaseDifference diff;
    
    if (!db1.isOpen() || !db2.isOpen()) {
        emit comparisonError(tr("One or both databases are not open"));
        return diff;
    }
    
    diff.databaseName1 = db1.databaseName();
    diff.databaseName2 = db2.databaseName();
    
    // 提取两个数据库的信息
    DatabaseInfo dbInfo1 = extractDatabaseInfo(db1);
    DatabaseInfo dbInfo2 = extractDatabaseInfo(db2);
    
    emit comparisonProgress(25);
    
    // 比较表
    QMap<QString, TableInfo> tables1, tables2;
    
    // 建立表名到表信息的映射
    for (const TableInfo &table : dbInfo1.tables) {
        tables1[table.name] = table;
    }
    
    for (const TableInfo &table : dbInfo2.tables) {
        tables2[table.name] = table;
    }
    
    emit comparisonProgress(50);
    
    // 查找新增的表
    for (const QString &tableName : tables2.keys()) {
        if (!tables1.contains(tableName)) {
            diff.tableDifferences.append(TableDifference(TableDifference::Added, tableName, tr("Table added")));
        }
    }
    
    // 查找删除的表
    for (const QString &tableName : tables1.keys()) {
        if (!tables2.contains(tableName)) {
            diff.tableDifferences.append(TableDifference(TableDifference::Removed, tableName, tr("Table removed")));
        }
    }
    
    // 查找修改的表
    for (const QString &tableName : tables1.keys()) {
        if (tables2.contains(tableName)) {
            TableInfo table1 = tables1[tableName];
            TableInfo table2 = tables2[tableName];
            
            // 比较表结构
            QList<TableDifference> tableDiffs = compareTables(table1, table2);
            diff.tableDifferences.append(tableDiffs);
        }
    }
    
    emit comparisonProgress(75);
    
    // 生成摘要
    diff.summary = generateSummary(diff.tableDifferences);
    
    emit comparisonProgress(100);
    emit comparisonFinished(diff);
    
    return diff;
}

QList<TableDifference> DatabaseDiff::compareTables(const TableInfo &table1, const TableInfo &table2)
{
    QList<TableDifference> differences;
    
    // 比较列
    for (const QString &columnName : table2.columns.keys()) {
        if (!table1.columns.contains(columnName)) {
            differences.append(TableDifference(TableDifference::Added, table1.name, 
                                             tr("Column '%1' added with type '%2'")
                                             .arg(columnName).arg(table2.columns[columnName])));
        } else if (table1.columns[columnName] != table2.columns[columnName]) {
            differences.append(TableDifference(TableDifference::Modified, table1.name, 
                                             tr("Column '%1' type changed from '%2' to '%3'")
                                             .arg(columnName)
                                             .arg(table1.columns[columnName])
                                             .arg(table2.columns[columnName])));
        }
    }
    
    for (const QString &columnName : table1.columns.keys()) {
        if (!table2.columns.contains(columnName)) {
            differences.append(TableDifference(TableDifference::Removed, table1.name, 
                                             tr("Column '%1' removed").arg(columnName)));
        }
    }
    
    // 比较主键
    if (table1.primaryKey != table2.primaryKey) {
        differences.append(TableDifference(TableDifference::Modified, table1.name, 
                                         tr("Primary key changed from '%1' to '%2'")
                                         .arg(table1.primaryKey.join(", "))
                                         .arg(table2.primaryKey.join(", "))));
    }
    
    // 比较外键
    for (const QString &columnName : table2.foreignKeys.keys()) {
        if (!table1.foreignKeys.contains(columnName)) {
            differences.append(TableDifference(TableDifference::Added, table1.name, 
                                             tr("Foreign key '%1' added referencing '%2'")
                                             .arg(columnName).arg(table2.foreignKeys[columnName])));
        } else if (table1.foreignKeys[columnName] != table2.foreignKeys[columnName]) {
            differences.append(TableDifference(TableDifference::Modified, table1.name, 
                                             tr("Foreign key '%1' changed from '%2' to '%3'")
                                             .arg(columnName)
                                             .arg(table1.foreignKeys[columnName])
                                             .arg(table2.foreignKeys[columnName])));
        }
    }
    
    for (const QString &columnName : table1.foreignKeys.keys()) {
        if (!table2.foreignKeys.contains(columnName)) {
            differences.append(TableDifference(TableDifference::Removed, table1.name, 
                                             tr("Foreign key '%1' removed").arg(columnName)));
        }
    }
    
    return differences;
}

QString DatabaseDiff::generateSummary(const QList<TableDifference> &differences)
{
    int added = 0, removed = 0, modified = 0;
    
    for (const TableDifference &diff : differences) {
        switch (diff.type) {
        case TableDifference::Added:
            added++;
            break;
        case TableDifference::Removed:
            removed++;
            break;
        case TableDifference::Modified:
            modified++;
            break;
        }
    }
    
    return tr("Database comparison summary:\n"
              "  %1 table(s) added\n"
              "  %2 table(s) removed\n"
              "  %3 table(s) modified")
            .arg(added).arg(removed).arg(modified);
}